package com.gs.protobuf.swing;

import com.gs.common.tool.pojo.OptionItem;
import com.gs.common.tool.utils.SwingUtil;
import com.gs.protobuf.enums.ProtoVersionEnum;
import com.gs.protobuf.utils.ProtocCompilerUtil;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.Arrays;
import java.util.Objects;

public class MainFrame {
    private JFrame frame;
    private JTextField protoField;
    private JTextField outputField;
    private JTextField packageField;
    private JComboBox<OptionItem> comboBox;
    private JTextArea logArea;           // 日志输出区域

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            try {
                UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }
            new MainFrame().createAndShowGUI();
        });
    }

    public void createAndShowGUI() {
        frame = new JFrame("Protobuf Java 生成工具");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(700, 500);
        frame.setLayout(new BorderLayout());

        // 顶部面板：输入区域
        JPanel inputPanel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(10, 10, 10, 10);
        gbc.fill = GridBagConstraints.HORIZONTAL;

        // Proto 文件
        gbc.gridx = 0;
        gbc.gridy = 0;
        inputPanel.add(new JLabel("Proto 文件:"), gbc);
        protoField = new JTextField(25);
        gbc.gridx = 1;
        inputPanel.add(protoField, gbc);
        JButton browseProtoBtn = new JButton("浏览");
        gbc.gridx = 2;
        inputPanel.add(browseProtoBtn, gbc);

        // 输出目录
        gbc.gridx = 0;
        gbc.gridy = 1;
        inputPanel.add(new JLabel("Java 输出目录:"), gbc);
        outputField = new JTextField(25);
        gbc.gridx = 1;
        inputPanel.add(outputField, gbc);
        JButton browseOutputBtn = new JButton("浏览");
        gbc.gridx = 2;
        inputPanel.add(browseOutputBtn, gbc);

        //添加proto版本下拉
        gbc.gridx = 0;
        gbc.gridy = 2;
        inputPanel.add(new JLabel("Proto协议版本:"), gbc);
        gbc.gridx = 1;
        comboBox = new JComboBox<>(getProtoList());
        inputPanel.add(comboBox, gbc);

        // 包路径
        gbc.gridx = 0;
        gbc.gridy = 3;
        inputPanel.add(new JLabel("包名:(非必填)"), gbc);
        packageField = new JTextField(25);
        gbc.gridx = 1;
        inputPanel.add(packageField, gbc);

        // 生成按钮
        JButton generateBtn = new JButton("生成 Java 文件");
        gbc.gridx = 1;
        gbc.gridy = 4;
        gbc.gridwidth = 2;
        gbc.anchor = GridBagConstraints.CENTER;
        inputPanel.add(generateBtn, gbc);

        // 日志区域
        logArea = new JTextArea();
        logArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
        logArea.setEditable(false);
        // 滚动条
        JScrollPane logScrollPane = new JScrollPane(logArea);

        // 添加到主窗口
        frame.add(inputPanel, BorderLayout.NORTH);
        frame.add(logScrollPane, BorderLayout.CENTER);

        // 事件绑定
        browseProtoBtn.addActionListener(e -> browseFile(protoField, "Select .proto file", "proto"));
        browseOutputBtn.addActionListener(e -> browseDirectory(outputField, "Select output directory"));
        //自定义下拉框显示
        SwingUtil.showComboBox(comboBox);
        generateBtn.addActionListener(e -> generateJava());
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void browseFile(JTextField field, String title, String ext) {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle(title);
        fc.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter(ext.toUpperCase() + " files", ext));
        if (fc.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
            field.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }

    private void browseDirectory(JTextField field, String title) {
        JFileChooser fc = new JFileChooser();
        fc.setDialogTitle(title);
        fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        if (fc.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
            field.setText(fc.getSelectedFile().getAbsolutePath());
        }
    }

    private void generateJava() {
        logArea.setText(""); // 清空日志
        log("开始生成 Java 文件...\n");

        String protoPath = protoField.getText().trim();
        String outputPath = outputField.getText().trim();
        String packageName = packageField.getText().trim();
        //proto版本，默认v3
        String protoVersion = ProtoVersionEnum.VERSION_3.getShortName();
        OptionItem proto = (OptionItem) comboBox.getSelectedItem();
        if (Objects.nonNull(proto)) {
            protoVersion = proto.getKey();
        }
        // 校验输入
        if (protoPath.isEmpty()) {
            logWithColor(false, "错误：请选择 .proto 文件");
            return;
        }
        if (outputPath.isEmpty()) {
            logWithColor(false, "错误：请选择 Java 输出目录");
            return;
        }
//        if (packageName.isEmpty() || !isValidPackageName(packageName)) {
//            logWithColor(false,"错误：包名格式无效（应为小写字母开头，如：com.example.dto）");
//            return;
//        }

        File protoFile = new File(protoPath);
        if (!protoFile.exists()) {
            logWithColor(false, "错误：Proto 文件不存在");
            return;
        }

        File outputDir = new File(outputPath);
        if (!outputDir.exists()) {
            if (!outputDir.mkdirs()) {
                logWithColor(false, "错误：无法创建输出目录");
                return;
            }
            log("提示：已创建输出目录\n");
        }
        if (!outputDir.isDirectory()) {
            logWithColor(false, "错误：输出路径不是有效目录");
            return;
        }

        // 调用编译器
        try {
            ProtocCompilerUtil.compile(protoFile, outputDir, protoVersion, packageName, this::logWithColor);
        } catch (Exception e) {
            logWithColor(false, "❌ 生成失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 日志方法
    private void log(String msg) {
        logArea.append(msg + "\n");
    }

    private void logWithColor(boolean isSuccess, String msg) {
        logArea.append(msg + "\n");
        if (isSuccess) {
            logArea.setForeground(new Color(0, 150, 0)); // 深绿色
        } else {
            logArea.setForeground(Color.RED);
        }
    }

    // 简单包名校验
    private boolean isValidPackageName(String pkg) {
        return pkg.matches("^[a-z][a-zA-Z0-9_]*(\\.[a-z][a-zA-Z0-9_]*)*$");
    }


    /**
     * 获取下拉元素
     *
     */
    private static OptionItem[] getProtoList() {
        return Arrays.stream(ProtoVersionEnum.values()).map(d -> {
            OptionItem optionItem = new OptionItem();
            optionItem.setKey(d.getShortName()).setValue(d.getFullName());
            return optionItem;
        }).toArray(OptionItem[]::new);
    }
}